package ac.manchester.cs.afzal.tcm_processing.term_similarities;

import ac.manchester.cs.afzal.tcm_processing.sql_handler.SQL_Handler_Comparisons_Impl;
import ac.manchester.cs.afzal.tcm_processing.miscellaneous.*;
import ac.manchester.cs.afzal.tcm_processing.nlp.*;
import java.io.*;
import java.text.DecimalFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Title: Term Classifier
 * @author Hammad Afzal
 * @version 1.0
 * Last Modification Date: 22 Jan, 2013
 *
 * How to run: Only change the LEXICAL_COMPARISON_TABLE, SOURCE and CORPUS_TERMS_PATH
 * You may want to disable the stop_word filtration

 */
public class Comparison_Lexical
{

    private String database_url = "database_url";
    private String username = "username";
    private String password = "password";

    private String SEED_TERMS_PATH = "SEED_TERMS_PATH";
    private String STOP_WORDS_PATH = "STOP_WORDS_PATH";
    private String CORPUS_TERMS_PATH = "CORPUS_TERMS_PATH"; // Directory containing files that has list of terms
    private String LEXICAL_COMPARISON_TABLE = "LEXICAL_COMPARISON_TABLE";
    private String SOURCE = "SOURCE";

    public Vector<String> seed_nodes;
    public Vector<String>[] profile_seed_terms, set_corpus_terms;

    File_Manager_Impl file_manager = new File_Manager_Impl();
    Vector_Builder_Impl vector_builder = new Vector_Builder_Impl();
    Lexical_Profile_Impl profile_builder = new Lexical_Profile_Impl();
    String_Manipulator_Impl str_man = new String_Manipulator_Impl();
    SQL_Handler_Comparisons_Impl sql_handler = new SQL_Handler_Comparisons_Impl();

    public Comparison_Lexical()
    {
        Properties props = new Properties();
        try
        {
            props.load(new FileInputStream("Term_Classification.properties"));
        }
        catch (IOException ex)
        {
            Logger.getLogger(Comparison_Lexical.class.getName()).log(Level.SEVERE, null, ex);
        }
        database_url = props.getProperty(database_url);
        username = props.getProperty(username);
        password = props.getProperty(password);

        SEED_TERMS_PATH = props.getProperty(SEED_TERMS_PATH);
        STOP_WORDS_PATH = props.getProperty(STOP_WORDS_PATH);
        CORPUS_TERMS_PATH = props.getProperty(CORPUS_TERMS_PATH);
        LEXICAL_COMPARISON_TABLE = props.getProperty(LEXICAL_COMPARISON_TABLE);
        SOURCE = props.getProperty(SOURCE);

        sql_handler.initialize_parameters(database_url, username, password);
        sql_handler.connect_db();
        sql_handler.reset_tables(new String[]{LEXICAL_COMPARISON_TABLE});


        seed_profile_builder(SEED_TERMS_PATH);
        calculate_similarity();

    }

    private void seed_profile_builder(String path)
    {
        String[] seed_terms;

        StringBuffer contents = file_manager.fileReader(path);
        Vector<String> seed_terms_vector = vector_builder.string_to_vector(contents.toString(), "\n");
        profile_seed_terms = new Vector[seed_terms_vector.size()];

        for (int n = 0; n < seed_terms_vector.size(); n++)
        {
            Vector words_in_mwt = new Vector();
            String seed_term_value = seed_terms_vector.elementAt(n);
            seed_term_value = seed_term_value.trim();
            seed_term_value = seed_term_value.toLowerCase();

            StringTokenizer tokenizer = new StringTokenizer(seed_term_value, " ");
            while (tokenizer.hasMoreTokens())
            {
                words_in_mwt.add(tokenizer.nextToken().toLowerCase());
            }
            seed_terms = (String[]) words_in_mwt.toArray(new String[words_in_mwt.size()]);
            profile_seed_terms[n] = profile_builder.term_profiles(seed_terms);
            if (profile_seed_terms[n].size() > 1)
            {
                profile_seed_terms[n].add(seed_term_value);
            }
        }
        System.out.println("Finished loading seed terms");
        System.out.println("Total seed terms loaded: " + profile_seed_terms.length);

    }

    private void calculate_similarity()
    {
        sql_handler.get_all_corpus_terms();
        Vector<String> corpus_terms_vector = sql_handler.get_whole_corpus_terms();
        Vector corpus_term_ids_vector = sql_handler.get_term_ids();

        System.out.println("No of corpus terms is : " + corpus_terms_vector.size());
        System.out.println("No of corpus term ids is : " + corpus_term_ids_vector.size());


        int no_of_corpus_terms = corpus_terms_vector.size();
        set_corpus_terms = new Vector[corpus_terms_vector.size()];

        /*********************** START - Making profiles of corpus terms ***********************************/
        for (int n = 0; n < corpus_terms_vector.size(); n++)
        {
            Vector words_in_mwt = new Vector();
            String corpus_term_value = corpus_terms_vector.elementAt(n);
            corpus_term_value = corpus_term_value.trim();
            corpus_term_value = corpus_term_value.toLowerCase();

            StringTokenizer tokenizer = new StringTokenizer(corpus_term_value, " ");
            while (tokenizer.hasMoreTokens())
            {
                words_in_mwt.add(tokenizer.nextToken().toLowerCase());
            }
            set_corpus_terms[n] = profile_builder.term_profiles((String[]) words_in_mwt.toArray(new String[words_in_mwt.size()]));
            if (set_corpus_terms[n].size() > 1)
            {
                set_corpus_terms[n].add(corpus_term_value);
            }
        }



        int iteration = 0;
        float[] terms_relevance = new float[no_of_corpus_terms];
        float[] terms_relevance_max = new float[no_of_corpus_terms];

        List matched_terms = new ArrayList<String>();

        for (int corpus_terms_count = 0; corpus_terms_count < no_of_corpus_terms; corpus_terms_count++)
        {
            float TOTAL_INTERSECTION = 0;
            int flag = 0;
            float max = 0;

            Vector<String> current_corpus_term_profile = set_corpus_terms[corpus_terms_count];

            for (int seed_terms_count = 0; seed_terms_count < profile_seed_terms.length; seed_terms_count++)
            {
                int intersection_per_seed_term = 0;
                Iterator<String> iter = current_corpus_term_profile.iterator();
                String element = null;

                Vector<String> current_seed_term_profile = profile_seed_terms[seed_terms_count];

                while (iter.hasNext())
                {
                    element = iter.next();
                    element = element.trim();
                    if (current_seed_term_profile.contains(element))
                    {
                        flag++;
                        intersection_per_seed_term++;
                        if (!(matched_terms.contains(element)))
                            matched_terms.add(element + System.getProperty("line.separator"));
                    }
                }
                float temp;
                {
                    temp = (float) (2 * intersection_per_seed_term) / (current_corpus_term_profile.size() + current_seed_term_profile.size());
                }

                max = (max < temp)? temp : max;

                TOTAL_INTERSECTION = TOTAL_INTERSECTION + temp;
                intersection_per_seed_term = 0;
                iteration++;
                flag = 0;
            }

            System.out.println("Term : " + set_corpus_terms[corpus_terms_count] + " Relevance : " + TOTAL_INTERSECTION);

            terms_relevance[corpus_terms_count] = (float) (TOTAL_INTERSECTION / profile_seed_terms.length);
            terms_relevance_max[corpus_terms_count] = max;
            TOTAL_INTERSECTION = 0;
        }
        file_manager.fileWriter(matched_terms.toString(), "Common_Terms.txt");

        /*********************** END - Adding Functionality of Similarity Calculation ***********************************/
        String[] relevance_value = new String[4];
        String[] doc_table1 =
        {
            "Term_ID", "Rel_1", "Rel_2", "Source"
        };


        for (int k = 0; k < set_corpus_terms.length; k++)
        {
            float man;
            float max = 0;
            man = terms_relevance_max[k];
            float relevance_lr1, relevance_lr2;

            relevance_lr1 = (terms_relevance[k]);
            relevance_lr1 = truncate(relevance_lr1);

            max = (man > max) ? man : max;
            relevance_lr2 = max;
            relevance_lr2 = truncate(relevance_lr2);

            Integer temp = new Integer(corpus_term_ids_vector.elementAt(k).toString());
            String term_id = temp.toString();
            relevance_value[0] = term_id;
            relevance_value[1] = Double.toString(relevance_lr1);
            relevance_value[2] = Double.toString(relevance_lr2);
            relevance_value[3] = SOURCE;

            sql_handler.insert_table(LEXICAL_COMPARISON_TABLE, doc_table1, relevance_value);
        }
        sql_handler.close_db();
    }

    private float truncate(float x)
    {
        DecimalFormat df = new DecimalFormat("0.##");
        String d = df.format(x);
        d = d.replaceAll(",", ".");
        Float dbl = new Float(d);
        return dbl.floatValue();
    }


}
